home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1995 November / Macworld Nov ’95.toast / Developers / Sources / cellusoftspritesrc.sit.hqx / cellusoftspritesrc.sit / Cellusoft Graphics / CellusoftAnimations.c < prev    next >
Encoding:
Text File  |  1993-12-27  |  18.3 KB  |  578 lines

  1. //• Most procedures in this file were created by Tony Small, author 
  2. //• of Cellusoft games.  You may feel free to pass this code along 
  3. //• to whom ever you like and look through the code and learn from it at 
  4. //• your leisure.
  5.  
  6. //• If, however, you choose to use any of the code below in one of 
  7. //• your programs, you are first obligated to pay the standard
  8. //• shareware fee of $15.  Upon payment of the fee, you may use any 
  9. //• of the following procedures or the unit as a whole as many times 
  10. //• as you choose in as many projects that you choose.    It would 
  11. //• also be appreciated if you mention Tony Small in the credits of 
  12. //• any program you use his procedures in.
  13.  
  14. //• Those who pay the shareware fee of $15 will also be informed of 
  15. //• future Cellusoft games and future Cellusoft programming routines.  
  16. //• Registered users will also be able to beta test all future 
  17. //• Cellusoft games and be named in the credits when appropriate.
  18.  
  19. //• In order to register, please send $15 to:     
  20. //•         Tony Small
  21. //•         18606 Cassandra St.
  22. //•         Tarzana, CA 91356
  23.  
  24. //• CellusoftAnimations© 1993 Tony Small - All Rights Reserved 
  25. //• WorldWide
  26.  
  27. //• ***Note*** - to use these routines, you don't necessarily have 
  28. //• to understand them.  Simply read through the explanations in the 
  29. //• interface section below and examine how they are used in the 
  30. //• program sample file.
  31.  
  32. //• Questions?  Send mail or E-mail  AOL - TonyS33
  33.  
  34. //• This file was translated to C by Matt Burch - Singularity 
  35. //• Software. Also, all offscreen port routines were created from 
  36. //• modified Principia routines by Matt Burch. This translation is 
  37. //• BetaWare - don’t forget to send Tony his registration fee, but 
  38. //• it’d also be appreciated if you’d make Matt Burch a beta tester 
  39. //• for your game. You can contact him at:
  40.             
  41. //•             AOL:        Black Mac
  42. //•             Internet:    blackmac@aol.com
  43. //•             US Mail:    Matt Burch
  44. //•             2261 Roach St.
  45. //•             Salina, KS 67401
  46.  
  47. //• Stay tuned for more great code from Cellusoft and Singularity. 
  48. //• Also, be sure not to miss "Rapier: XF7500," 
  49. //• coming in summer ’93 from Singularity!
  50.  
  51.  
  52. #pragma once
  53. #include "Cellusoft.h"
  54. #include "GestaltEqu.h"
  55.  
  56. //• Maximum number of bytes in a row of pixels.
  57. #define kMaxRowBytes 0x3FFE     
  58.  
  59. //• Default resolution is 72 DPI; Fixed type.
  60. #define kDefaultRes 0x00480000
  61. #define kITabRes 4        //• Inverse-table resolution.
  62.  
  63. //• The following functions help to manage the actual animation process.  
  64. //• Call InitAnimations after every animation loop.
  65. //• InitAnimations will reset the animArray to its original state.
  66. //• Call SetAnimation to add an animation to the array. tlRect specifies 
  67. //• where the animated graphic was last on the screne.
  68. //• tcRect specifies where the animated graphic is now on the screne.  
  69. //• tpRect specifies the location of the graphic on the GrafPtr where the 
  70. //• actual picture to be animated is located.  
  71. //• ttheGraf is the port that holds that picture and tthemaskGraf is the 
  72. //• port with the mask of that picture.
  73. //• AnimateArray will animate all of the animations you specified with each 
  74. //• SetAnimation call.  The maximum number of animations there can be at 
  75. //• the same time is only limited by the constant MaxAnimations.  This 
  76. //• procedure also handled the collisions of any number of animations 
  77. //• without flicker.
  78. //• pureback is the port that holds the original picture of the background 
  79. //• graphic.  
  80. //• offLoad is a blank port the same size of the MainWindow.  
  81. //• MainWindow is the pointer to the window where the user will see the 
  82. //• animations take place.
  83. //• ***Note*** - The method of animation used was developed by John Calhoun, 
  84. //• author of Glider 4.0.  If you would like to learn more about the flicker 
  85. //• free technique used by his programs and by these routines, then look 
  86. //• for either Glypha 2.0 source code or Glypha Primer offered by John 
  87. //• Calhoun available on AOL and other bulletin boards.
  88.  
  89. //• The following two functions are simply easier ways to call 
  90. //• sometimes complicated system routines.
  91. //• Copy replaces CopyBits.  With this, you do not need to put 
  92. //• in ^.portbits and specify the regionhandle and other odd variables.
  93. //• This simply copies from Port1 to Port2, from Rect1 to Rect2.
  94. //• MoveRect moves TheRect, the specified integers.  MoveRect is 
  95. //• used by other CellusoftAnimations routines.*/
  96.  
  97. void Copy (GrafPtr Port1, GrafPtr Port2, Rect Rect1, Rect Rect2)
  98. {
  99.     CopyBits (& ((GrafPtr)Port1)->portBits, & ((GrafPtr)Port2)->portBits, &Rect1, &Rect2, 0, theregion);
  100. }
  101.  
  102. void AnimateArray (GrafPtr pureback, GrafPtr offLoad, WindowPtr mainWindow)
  103. {
  104.     int i, j;
  105.     Rect wRect[MaxAnimations+1];
  106.     Boolean col[MaxAnimations+1];
  107.     
  108.     for (i = 1; i <= MaxAnimations; i++)
  109.         if (animArray[i].active)
  110.             UnionRect (&animArray[i].lRect, 
  111.                       &animArray[i].cRect, 
  112.                       &wRect[i]);
  113.         
  114.     for (i = 1; i <= MaxAnimations; i++)
  115.     {
  116.         if (animArray [i].active)
  117.         {
  118.             for (j = i + 1; j <= MaxAnimations; j++)
  119.                 col[j] = FALSE;
  120.             tr [2] = wRect[i];
  121.             for (j = i + 1; j <= MaxAnimations; j++)
  122.             {
  123.                 if (animArray[j].active)
  124.                     if (SectRect (&tr[2], &wRect[j], &tr[1]))
  125.                     {
  126.                         col[j]=TRUE;
  127.                         animArray[j].active=false;
  128.                         UnionRect (&tr[2], &wRect[j], &tr[2]);
  129.                     }
  130.             }        
  131.             col[i]=TRUE;
  132.             Copy (pureback, offLoad, tr[2], tr[2]);
  133.         
  134.             for (j = i; j <= MaxAnimations; j++)
  135.             {
  136.                 if (col[j])
  137.                 {
  138.                     CopyMask (& ((GrafPtr)animArray[j].theGraf)->portBits,
  139.                             & ((GrafPtr)animArray[j].theMaskGraf)->portBits,
  140.                             & ((GrafPtr)offLoad)->portBits,
  141.                             &animArray[j].pRect,
  142.                             &animArray[j].pRect,
  143.                             &animArray[j].cRect);
  144.                     }
  145.                 }
  146.                     
  147.             Copy (offLoad, mainWindow, tr[2], tr[2]);
  148.             }
  149.         }
  150. }
  151.  
  152. void SetAnimation (Rect tlRect, Rect tcRect, Rect tpRect, GrafPtr ttheGraf, GrafPtr tthemaskGraf)
  153. {
  154.     int i;
  155.  
  156.     i = 1;
  157.     while ((animArray[i].active) && (i < MaxAnimations))
  158.         i++;
  159.         
  160.     animArray[i].active = TRUE;
  161.     animArray[i].lRect = tlRect;
  162.     animArray[i].cRect = tcRect;
  163.     animArray[i].pRect = tpRect;
  164.     animArray[i].theGraf = ttheGraf;
  165.     animArray[i].theMaskGraf = tthemaskGraf;
  166. }
  167.  
  168.  
  169. void InitAnimations ()
  170. {
  171.     int i;
  172.  
  173.     for (i = 1; i <= MaxAnimations; i++)
  174.         animArray[i].active = FALSE;
  175. }
  176.  
  177. void MoveRect (Rect *TheRect, int left, int up, int right, int down)
  178. {
  179.     TheRect->left = TheRect->left + left;
  180.     TheRect->top = TheRect->top + up;
  181.     TheRect->right = TheRect->right + right;
  182.     TheRect->bottom = TheRect->bottom + down;
  183. }    
  184.  
  185. DoAlert (Str255 a)            //• yell at the user
  186. {
  187.     ParamText (a, "\p", "\p", "\p");
  188.     StopAlert (128, nil);
  189. }
  190.  
  191. //• SetUpPixMap and CreateGDevice are used internally by the Cellusoft 
  192. //• routines ONLY. Your application shouldn’t have any reason to call these.
  193.  
  194. OSErr SetUpPixMap (short depth, Rect *bounds, CTabHandle colors, short bytesPerRow, PixMapHandle aPixMap)    
  195. {
  196.     CTabHandle newColors;    //• Color table used for the off-screen PixMap.
  197.     Ptr        offBaseAddr; //• Pointer to the off-screen pixel image.
  198.     OSErr      error;        //• Returns error code.
  199.  
  200.     error = noErr;
  201.     newColors = nil;
  202.     offBaseAddr = nil;
  203.  
  204.     //• Clone the clut if indexed color; allocate a dummy clut if direct color.
  205.     if (depth <= 8)
  206.     {
  207.         newColors = colors;
  208.         error = HandToHand ((Handle *)&newColors);
  209.     }
  210.     else
  211.     {
  212.         newColors = (CTabHandle)NewHandle (sizeof (ColorTable) -
  213.                 sizeof (CSpecArray));
  214.         error = MemError ();
  215.     }
  216.     if (error == noErr)
  217.     {
  218.         //• Allocate pixel image; long integer multiplication avoids overflow.
  219.         offBaseAddr = NewPtr ((unsigned long)bytesPerRow * (bounds->bottom -
  220.                 bounds->top));
  221.         if (offBaseAddr != nil)
  222.         {
  223.             //• Initialize fields common to indexed and direct PixMaps.
  224.             (**aPixMap).baseAddr = offBaseAddr;  //• Point to image.
  225.             (**aPixMap).rowBytes = bytesPerRow | //• MSB set for PixMap.
  226.                     0x8000;
  227.             (**aPixMap).bounds = *bounds;        //• Use given bounds.
  228.             (**aPixMap).pmVersion = 0;            //• No special stuff.
  229.             (**aPixMap).packType = 0;            //• Default PICT pack.
  230.             (**aPixMap).packSize = 0;            //• Always zero in mem.
  231.             (**aPixMap).hRes = kDefaultRes;      //• 72 DPI default res.
  232.             (**aPixMap).vRes = kDefaultRes;      //• 72 DPI default res.
  233.             (**aPixMap).pixelSize = depth;        //• Set # bits/pixel.
  234.             (**aPixMap).planeBytes = 0;          //• Not used.
  235.             (**aPixMap).pmReserved = 0;          //• Not used.
  236.  
  237.             //• Initialize fields specific to indexed and direct PixMaps.
  238.             if (depth <= 8)
  239.             {
  240.                 //• PixMap is indexed.
  241.                 (**aPixMap).pixelType = 0;        //• Indicates indexed.
  242.                 (**aPixMap).cmpCount = 1;        //• Have 1 component.
  243.                 (**aPixMap).cmpSize = depth;     //• Component size=depth.
  244.                 (**aPixMap).pmTable = newColors; //• Handle to CLUT.
  245.             }
  246.             else
  247.                 {
  248.                 //• PixMap is direct.
  249.                  (**aPixMap).pixelType = RGBDirect; //• Indicates direct.
  250.                 (**aPixMap).cmpCount = 3;          //• Have 3 components.
  251.                 if (depth == 16)
  252.                     (**aPixMap).cmpSize = 5;        //• 5 bits/component.
  253.                 else
  254.                     (**aPixMap).cmpSize = 8;        //• 8 bits/component.
  255.                     (**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
  256.                     (**newColors).ctFlags = 0;
  257.                     (**newColors).ctSize = 0;
  258.                     (**aPixMap).pmTable = newColors;
  259.             }
  260.         }
  261.         else
  262.             error = MemError ();
  263.     }
  264.     else
  265.         newColors = nil;
  266.  
  267.     //• If no errors occurred, return a handle to the new off-screen PixMap.
  268.     if (error != noErr)
  269.     {
  270.         if (newColors != nil)
  271.             DisposCTable (newColors);
  272.     }
  273.  
  274.     //• Return the error code.
  275.     return error;
  276. }
  277.  
  278. //• CreateOffScreen takes a CGrafPtr and makes an offscreen port out of it. 
  279. //• The first two parameters are the width and heighth (in pixels) of the 
  280. //• port you want created.
  281. //• The third parameter is the pixel depth of the port. Pass it at 1 for 
  282. //• a black and white port, an 8 for a 256-color port, etc. If you pass it 
  283. //• a 0, it will use the current bit depth of the screen, which is useful 
  284. //• if you want your program to be adaptable to different screens.
  285. //• The fourth parameter is a pointer to your new port.    It normally takes a 
  286. //• CGrafPtr, but you can also use it to dispose of a regular GrafPtr by 
  287. //• using a (CGrafPtr) typecast. Example call:
  288. //•         CreateOffScreen (300, 300, 8, & (CGrafPtr)myGrafPtr, 400);
  289. //• The last argument is the ID number of a pict, if you want to place one 
  290. //• in your port. If you desire a blank port, just pass a -1 instead.
  291.  
  292. OSErr CreateOffScreen (
  293.     int            right, 
  294.     int         bottom,
  295.     short        depth,
  296.     CGrafPtr    *retPort,
  297.     int            picID)
  298. {
  299.     CGrafPtr     newPort;     //• Pointer to the new off-screen CGrafPort.
  300.     PixMapHandle newPixMap;    //• Handle to the new off-screen PixMap.
  301.     GDHandle     newDevice;    //• Handle to the new off-screen GDevice.
  302.     long         qdVersion;    //• Version of QuickDraw currently in use.
  303.     GrafPtr      savedPort;    //• Pointer to GrafPort used for save/restore.
  304.     SignedByte    savedState;  //• Saved state of color table handle.
  305.     short        bytesPerRow; //• Number of bytes per row in the PixMap.
  306.     OSErr        error;        //• Returns error code.
  307.     CTabHandle     colors;
  308.     Rect         bounds;
  309.     PicHandle     pic;
  310.     
  311.     
  312.     if (depth==0)
  313.         depth = (** ((**GetMainDevice ()).gdPMap)).pixelSize;
  314.  
  315.     colors = GetCTable (depth);    
  316.     SetRect (&bounds, 0, 0, right, bottom);
  317.  
  318.     //• Initialize a few things before we begin.
  319.     newPort = nil;
  320.     newPixMap = nil;
  321.     newDevice = nil;
  322.     error = noErr;
  323.  
  324.     //• Save the color table’s current state and make sure it isn’t purgeable.
  325.     if (colors != nil)
  326.     {
  327.         savedState = HGetState ((Handle)colors);
  328.         HNoPurge ((Handle)colors);
  329.     }
  330.  
  331.     //• Calculate the number of bytes per row in the off-screen PixMap.
  332.     bytesPerRow = ((depth * (bounds.right - bounds.left) + 31) >> 5) << 2;
  333.  
  334.     //• Get the current QuickDraw version.
  335.     (void)Gestalt (gestaltQuickdrawVersion, &qdVersion);
  336.  
  337.     //• Make sure depth is indexed or depth is direct and 32-Bit QD installed.
  338.     if (depth == 1 || depth == 2 || depth == 4 || depth == 8 ||
  339.             ((depth == 16 || depth == 32) && qdVersion >= gestalt32BitQD))
  340.     {
  341.         //• Maximum number of bytes per row is 16,382; make sure within range.
  342.         if (bytesPerRow <= kMaxRowBytes)
  343.         {
  344.             //• Make sure a color table is provided if the depth is indexed.
  345.             if (depth <= 8)
  346.                 if (colors == nil)
  347.                   //• Indexed depth and clut is NIL; is parameter error.
  348.                   error = paramErr;
  349.         }
  350.         else
  351.             //• # of bytes per row is more than 16,382; is parameter error.
  352.             error = paramErr;
  353.     }
  354.     else
  355.         //• Pixel depth isn’t valid; is parameter error.
  356.         error = paramErr;
  357.  
  358.     //• If sanity checks succeed, then allocate a new CGrafPort.
  359.     if (error == noErr)
  360.     {
  361.         newPort = (CGrafPtr)NewPtr (sizeof (CGrafPort));
  362.         if (newPort != nil)
  363.         {
  364.             //• Save the current port.
  365.             GetPort (&savedPort);
  366.  
  367.             //• Initialize the new CGrafPort and make it the current port.
  368.             OpenCPort (newPort);
  369.  
  370.             //• Set portRect, visRgn, and clipRgn to the given bounds rect.
  371.             newPort->portRect = bounds;
  372.             RectRgn (newPort->visRgn, &bounds);
  373.             ClipRect (&bounds);
  374.  
  375.             //• Initialize the new PixMap for off-screen drawing.
  376.             error = SetUpPixMap (depth, &bounds, colors, bytesPerRow,
  377.                     newPort->portPixMap);
  378.             if (error == noErr)
  379.             {
  380.                 //• Grab the initialized PixMap handle.
  381.                 newPixMap = newPort->portPixMap;
  382.  
  383.                 //• Allocate and initialize a new GDevice.
  384.                 error = CreateGDevice (newPixMap, &newDevice);
  385.             }
  386.  
  387.             EraseRect (&bounds);
  388.  
  389.             if (picID!=-1)
  390.                 {
  391.                 pic=GetPicture (picID);
  392.                 if (pic!=nil)
  393.                     DrawPicture (pic, &bounds);
  394.                     
  395.                 }
  396.             
  397.             //• Restore the saved port.
  398.             SetPort (savedPort);
  399.         }
  400.         else
  401.             error = MemError ();
  402.     }
  403.  
  404.     //• Restore the given state of the color table.
  405.     if (colors != nil)
  406.         HSetState ((Handle)colors, savedState);
  407.  
  408.     //• One Last Look Around The House Before We Go….
  409.     if (error != noErr)
  410.     {
  411.         //• Some error occurred; dispose of everything we allocated.
  412.         if (newPixMap != nil)
  413.         {
  414.             DisposCTable ((**newPixMap).pmTable);
  415.             DisposPtr ((**newPixMap).baseAddr);
  416.         }
  417.         if (newDevice != nil)
  418.         {
  419.             DisposHandle ((Handle) (**newDevice).gdITable);
  420.             DisposHandle ((Handle)newDevice);
  421.         }
  422.         if (newPort != nil)
  423.         {
  424.             CloseCPort (newPort);
  425.             DisposPtr ((Ptr)newPort);
  426.         }
  427.     }
  428.     else
  429.     {
  430.         //• Everything’s OK; return refs to off-screen CGrafPort and GDevice.
  431.         *retPort = newPort;
  432. //        *retGDevice = newDevice;
  433.     }
  434.     return error;
  435. }
  436.  
  437. //• This function will take the GrafPtr Origin, and create a port of 
  438. //• identical size called Destination and effectively perform a
  439. //• horizontal swap of the picture on Origin.  This procedure is good 
  440. //• to use if you want to save disk space by not having to put 
  441. //• horizontally swapped pictures into the resource.  Set the 
  442. //• variable Color to true if the GrafPtr is a color port.
  443.  
  444. void HorizontalFlip (GrafPtr *Origin, GrafPtr *Destination, Boolean Color)
  445. {
  446.     int i;
  447.     CGrafPtr tempPort;
  448.  
  449.     tr[1] = ((GrafPtr)Origin)->portRect;
  450.     tempPort = (CGrafPtr)*Destination;
  451.     if (Color)
  452.         CreateOffScreen (tr[1].right, tr[1].bottom, 0, &tempPort, -1);
  453.     else
  454.         CreateOffScreen (tr[1].right, tr[1].bottom, 1, &tempPort, -1);
  455.     *Destination= (GrafPtr)tempPort;
  456.     SetRect (&tr[2], 0, 0, 1, tr[1].bottom);
  457.     SetRect (&tr[3], tr[1].right - 1, 0, tr[1].right, tr[1].bottom);
  458.     for (i = 1; i <= tr[1].right; i++)
  459.     {
  460.         Copy (*Origin, *Destination, tr[2], tr[3]);
  461.         MoveRect (&tr[2], 1, 0, 1, 0);
  462.         MoveRect (&tr[3], -1, 0, -1, 0);
  463.     }
  464. }
  465.  
  466.  
  467. //• basePixMap - Handle to the PixMap to base GDevice on.
  468. //• *retGDevice - Returns a handle to the new GDevice.
  469. CreateGDevice (PixMapHandle basePixMap, GDHandle *retGDevice)
  470. {
  471.     GDHandle    newDevice;  //• Handle to the new GDevice.
  472.     ITabHandle embryoITab; //• Handle to the embryonic inverse table.
  473.     Rect        deviceRect; //• Rectangle of GDevice.
  474.     OSErr      error;      //• Error code.
  475.  
  476.     //• Initialize a few things before we begin.
  477.     error = noErr;
  478.     newDevice = nil;
  479.     embryoITab = nil;
  480.  
  481.     //• Allocate memory for the new GDevice.
  482.     newDevice = (GDHandle)NewHandle (sizeof (GDevice));
  483.     if (newDevice != nil)
  484.     {
  485.         //• Allocate the embryonic inverse table.
  486.         embryoITab = (ITabHandle)NewHandleClear (2);
  487.         if (embryoITab != nil)
  488.         {
  489.             //• Set rectangle of device to PixMap bounds.
  490.             deviceRect = (**basePixMap).bounds;
  491.  
  492.             //• Initialize the new GDevice fields.
  493.             (**newDevice).gdRefNum = 0;            //• Only used for screens.
  494.             (**newDevice).gdID = 0;                //• Won’t normally use.
  495.             if ((**basePixMap).pixelSize <= 8)
  496.                 (**newDevice).gdType = clutType;    //• Depth≤8; clut device.
  497.             else
  498.                 (**newDevice).gdType = directType; //• Depth>8; direct device.
  499.             (**newDevice).gdITable = embryoITab;    //• 2-byte handle for now.
  500.             (**newDevice).gdResPref = kITabRes;    //• Normal inv table res.
  501.             (**newDevice).gdSearchProc = nil;      //• No color-search proc.
  502.             (**newDevice).gdCompProc = nil;        //• No complement proc.
  503.             (**newDevice).gdFlags = 0;             //• Will set these later.
  504.             (**newDevice).gdPMap = basePixMap;     //• Reference our PixMap.
  505.             (**newDevice).gdRefCon = 0;            //• Won’t normally use.
  506.             (**newDevice).gdNextGD = nil;          //• Not in GDevice list.
  507.             (**newDevice).gdRect = deviceRect;     //• Use PixMap dimensions.
  508.             (**newDevice).gdMode = -1;             //• For nonscreens.
  509.             (**newDevice).gdCCBytes = 0;            //• Only used for screens.
  510.             (**newDevice).gdCCDepth = 0;            //• Only used for screens.
  511.             (**newDevice).gdCCXData = 0;            //• Only used for screens.
  512.             (**newDevice).gdCCXMask = 0;            //• Only used for screens.
  513.             (**newDevice).gdReserved = 0;          //• Currently unused.
  514.  
  515.             //• Set color-device bit if PixMap isn’t black & white.
  516.             if ((**basePixMap).pixelSize > 1)
  517.                 SetDeviceAttribute (newDevice, gdDevType, true);
  518.  
  519.             //• Set bit to indicate that the GDevice has no video driver.
  520.             SetDeviceAttribute (newDevice, noDriver, true);
  521.  
  522.             //• Initialize the inverse table.
  523.             if ((**basePixMap).pixelSize <= 8)
  524.             {
  525.                 MakeITable ((**basePixMap).pmTable, (**newDevice).gdITable,
  526.                         (**newDevice).gdResPref);
  527.                 error = QDError ();
  528.             }
  529.         }
  530.         else
  531.             error = MemError ();
  532.     }
  533.     else
  534.         error = MemError ();
  535.  
  536.     //• Handle any errors along the way.
  537.     if (error != noErr)
  538.     {
  539.         if (embryoITab != nil)
  540.             DisposHandle ((Handle)embryoITab);
  541.         if (newDevice != nil)
  542.             DisposHandle ((Handle)newDevice);
  543.     }
  544.     else
  545.         *retGDevice = newDevice;
  546.  
  547.     //• Return a handle to the new GDevice.
  548.     return error;
  549. }
  550.  
  551. //• DisposeOffScreen takes a CGrafPtr and disposes of it. It normally takes 
  552. //• a CGrafPtr, but you can also use it to dispose of a regular GrafPtr by 
  553. //• using a (CGrafPtr) typecast. Example call:
  554. //•         DisposeOffScreen ((CGrafPtr)myGrafPtr);
  555.  
  556. void DisposeOffScreen (
  557.     CGrafPtr doomedPort)    //• Pointer to the CGrafPort to be disposed of.
  558. {
  559.     CGrafPtr currPort;    //• Pointer to the current port.
  560.  
  561.     //• Check to see whether the doomed CGrafPort is the current port.
  562.     GetPort ((GrafPtr *)&currPort);
  563.     if (currPort == doomedPort)
  564.     {
  565.         //• It is; set current port to Window Manager CGrafPort.
  566.         GetCWMgrPort (&currPort);
  567.         SetPort ((GrafPtr)currPort);
  568.     }
  569.  
  570.     //• Throw everything away.
  571.     DisposPtr ((**doomedPort->portPixMap).baseAddr);
  572.     if ((**doomedPort->portPixMap).pmTable != nil)
  573.         DisposCTable ((**doomedPort->portPixMap).pmTable);
  574.     CloseCPort (doomedPort);
  575.     DisposPtr ((Ptr)doomedPort);
  576. }
  577.  
  578.